package com.shujia

object Demo8Func2 {
  def main(args: Array[String]): Unit = {
    /**
     * 函数式编程（高阶函数、面向函数编程）
     * 面向对象编程：把对象传来传去 注意在将对象传给函数的时候有类型的限制 以及 对象作为返回值的时候也有类型的限制
     * 面向函数编程：把函数传来传去 注意在将函数传给函数的时候有类型的限制 以及 函数作为返回值的时候也有类型的限制
     *
     * 函数式编程的分类：
     * 1、以函数作为参数
     * 2、以函数作为返回值
     *
     * 怎么去描述函数的类型？
     * 1、跟def关键字无关
     * 2、跟函数名也无关
     * 3、跟函数实现的功能也无关
     * 4、跟函数的参数名称也无关
     * 5、实际上函数的类型 由参数的类型（个数、顺序）及返回值的类型共同决定
     *
     * 参数的类型 => 返回值的类型
     *
     */

    println(func1("100")) // 101
    println(func2("100")) // 102

    println(funcX(func1)) // 201
    println(funcX(func2)) // 202
    //    funcX(func3)

    // 调用"匿名函数"
    println(ff("100", 4))

    // 如果函数逻辑比较简单 可以使用匿名函数进行简化
    println(funcX((str: String) => {str.toInt + 5})) // 205

    /**
     * 匿名函数的省略规则：
     * 1、函数体只有一行代码，花括号可以省略
     * 2、如果匿名函数作为另一个函数的参数传入 参数的类型可以省略
     * 3、如果参数只有一个 括号可以省略
     * 4、如果参数只被使用的一次 则可以省略 并用下划线_替代
     */
    println(funcX((str: String) => str.toInt + 6)) // 206
    println(funcX((str) => str.toInt + 6)) // 206
    println(funcX(str => str.toInt + 7)) // 207
    println(funcX(_.toInt + 8)) // 208


  }

  // func1 是一个 参数为String 返回值为Int类型 的函数
  def func1(str1: String): Int = str1.toInt + 1

  // func2 是一个 参数为String 返回值为Int类型 的函数
  def func2(str2: String): Int = str2.toInt + 2

  // func3 是一个 参数为Int 返回值为Int类型 的函数
  // func1和func2是同一类型
  // func3 不跟func1、func2同一类型
  def func3(i: Int): Int = i + 3

  // 接收一个函数 --> 该函数的类型为：参数是String类型，返回值是Int类型
  def funcX(f: String => Int): Int = {
    val i: Int = f("200")
    i
  }

  /**
   * 匿名函数 lambda
   *
   */
  // 定义了一个匿名函数：”参数有两个，类型分别为String、Int，返回值类型为Int“ 的函数
  (str1: String, int1: Int) => {
    str1.toInt + int1
  }

  // 匿名函数也可以拥有名字
  val ff: (String, Int) => Int = (str1: String, int1: Int) => {
    str1.toInt + int1
  }




}
